using System;
using System.Linq;
using Sirenix.OdinInspector;
using Sirenix.Serialization;
using UnityEngine;

namespace cmd
{
    [AssetList]
    public class PickableItemDataModelSO : SerializedScriptableObject
    {
        [field: OdinSerialize, Indent(-1)]
        public PickableItemDataModel PickableItemDataModel { get; protected set; } =
            new NormalFishData();

        [field: SerializeField]
        [field: LabelText("物品ID"), Tooltip("和物品类型组合使用")]
        public uint Id { get; protected set; }

        [Button(ButtonSizes.Medium), PropertySpace(10)]
        private void SetPickableItemId()
        {
            // 提取name开头的数字作为Id
            if (uint.TryParse(name.TakeWhile(c => char.IsDigit(c)).ToString(), out uint id))
            {
                Id = id;
            }
        }
    }

    /// <summary>
    /// 可拾取物品的基类
    /// </summary>
    public abstract class PickableItemDataModel
    {
        /// <summary>判断此可拾取物品的具体类型</summary>
        [ShowInInspector, ReadOnly]
        public abstract PickableItemType PickableItemType { get; }

        [Button("测试可拾取物品数据传输对象"), PropertySpace(20)]
        public abstract PickableItemDataDTO GetPickableItemDataDTO();

        public abstract PickableItemDataDTO GetPickableItemDataDTO(
            PickableItemDataOverride overrideData
        );
    }

    [Serializable]
    public class NormalFishData : PickableItemDataModel
    {
        #region 数据
        [field: SerializeField]
        [field: LabelText("种类")]
        public FishTypeDataSO FishTypeDataSO { get; init; }

        [field: SerializeField, HideLabel, Space(10)]
        // [field: LabelText("鱼类配置")]
        public PickableItemDataOverride FishTypeDataOverride { get; protected set; } =
            new()
            {
                IsOverrideQuality = false,
                QualityOverride = IntRange.CreateWithLimitation(1, 3),
                IsOverrideName = false,
                NameOverride = string.Empty,
                IsOverrideBaseWeight = false,
                BaseWeightOverride = FloatRange.CreateWithLimitation(0, 100),
                IsOverrideVolume = false,
                VolumeOverride = FloatRange.CreateWithLimitation(50, 150),
                IsOverrideMoveSpeed = false,
                MoveSpeedOverride = FloatRange.CreateWithLimitation(0, 10),
                IsOverrideSpawnRange = false,
                SpawnRangeOverride = FloatRange.CreateWithLimitation(0, 100)
            };

        #endregion

        #region 继承的功能
        public override PickableItemType PickableItemType => PickableItemType.Fish;

        public override PickableItemDataDTO GetPickableItemDataDTO() => GetFishDataDTO();

        public override PickableItemDataDTO GetPickableItemDataDTO(
            PickableItemDataOverride overrideData
        ) => GetFishDataDTO(overrideData);

        #endregion

        // [Button("测试生成鱼数据传输对象")]
        public FishDataDTO GetFishDataDTO()
        {
            if (FishTypeDataSO == null)
            {
                Debug.LogError($"错误，鱼类型数据不存在，检查是否存在未赋值的鱼数据");
                throw new ArgumentException("鱼类型数据不存在");
                // return null;
            }

            return new()
            {
                FishType = FishTypeDataSO.FishTypeData,

                Name = FishTypeDataOverride.IsOverrideName
                    ? FishTypeDataOverride.NameOverride
                    : FishTypeDataSO.FishTypeData.Name,

                Quality = FishTypeDataSO.FishTypeData.Quality.GetValue(),

                BaseWeight = FishTypeDataOverride.IsOverrideBaseWeight
                    ? FishTypeDataOverride.BaseWeightOverride.GetValue()
                    : FishTypeDataSO.FishTypeData.BaseWeight.GetValue(),

                Volume = FishTypeDataOverride.IsOverrideVolume
                    ? FishTypeDataOverride.VolumeOverride.GetValue()
                    : RandomGenerater.GenerateTriangularDistribution(
                        FishTypeDataSO.FishTypeData.VolumeRange
                    ),

                MoveSpeed = FishTypeDataOverride.IsOverrideMoveSpeed
                    ? FishTypeDataOverride.MoveSpeedOverride.GetValue()
                    : FishTypeDataSO.FishTypeData.MoveSpeed.GetValue(),

                SpawnRangePercent = FishTypeDataOverride.IsOverrideSpawnRange
                    ? FishTypeDataOverride.SpawnRangeOverride.GetValue()
                    : FishTypeDataSO.FishTypeData.SpawnRangePercent.GetValue(),

                UnitValue = FishTypeDataOverride.IsOverrideUnitValue
                    ? FishTypeDataOverride.UnitValueOverride.GetValue()
                    : FishTypeDataSO.FishTypeData.UnitValue.GetValue()
            };
        }

        public FishDataDTO GetFishDataDTO(PickableItemDataOverride overrideData) =>
            new()
            {
                FishType = FishTypeDataSO.FishTypeData,

                Name = overrideData.IsOverrideName
                    ? overrideData.NameOverride
                    : FishTypeDataSO.FishTypeData.Name,

                Quality = FishTypeDataSO.FishTypeData.Quality.GetValue(),

                BaseWeight = overrideData.IsOverrideBaseWeight
                    ? overrideData.BaseWeightOverride.GetValue()
                    : FishTypeDataSO.FishTypeData.BaseWeight.GetValue(),

                Volume = overrideData.IsOverrideVolume
                    ? overrideData.VolumeOverride.GetValue()
                    : RandomGenerater.GenerateTriangularDistribution(
                        FishTypeDataSO.FishTypeData.VolumeRange
                    ),

                MoveSpeed = overrideData.IsOverrideMoveSpeed
                    ? overrideData.MoveSpeedOverride.GetValue()
                    : FishTypeDataSO.FishTypeData.MoveSpeed.GetValue(),

                SpawnRangePercent = overrideData.IsOverrideSpawnRange
                    ? overrideData.SpawnRangeOverride.GetValue()
                    : FishTypeDataSO.FishTypeData.SpawnRangePercent.GetValue(),

                UnitValue = overrideData.IsOverrideUnitValue
                    ? overrideData.UnitValueOverride.GetValue()
                    : FishTypeDataSO.FishTypeData.UnitValue.GetValue()
            };
    }

    /// <summary>可拾取物品数据传输对象，包含了确定好的、不可修改的，从模型得到的可拾取物品数据</summary>
    [Serializable]
    public class PickableItemDataDTO : IEquatable<PickableItemDataDTO>
    {
        /// <summary>
        /// 可拾取物品的名字
        /// </summary>
        [field: SerializeField]
        public string Name { get; init; }

        /// <summary>
        /// 可拾取物品的品质等级
        /// </summary>
        [field: SerializeField]
        public int Quality { get; init; }

        /// <summary>
        /// 可拾取物品的体积大小(百分比)
        /// </summary>
        [field: SerializeField]
        public float Volume { get; init; }

        /// <summary>
        /// 可拾取物品的移动速度
        /// </summary>
        [field: SerializeField]
        public float MoveSpeed { get; init; }

        /// <summary>
        /// 可拾取物品的生成高度百分比(0-100)
        /// </summary>
        [field: SerializeField]
        public float SpawnRangePercent { get; init; }

        public virtual bool Equals(PickableItemDataDTO other) =>
            other != null
            && Name == other.Name
            && Quality == other.Quality
            && Volume == other.Volume
            && MoveSpeed == other.MoveSpeed
            && SpawnRangePercent == other.SpawnRangePercent;
    }

    [Serializable]
    public class FishDataDTO : PickableItemDataDTO
    {
        /// <summary>
        /// 鱼的种类标识
        /// </summary>
        [field: SerializeField, PropertyOrder(-10)]
        public FishTypeData FishType { get; init; }

        /// <summary>
        /// 鱼的基础重量
        /// </summary>
        [field: SerializeField]
        public float BaseWeight { get; init; }

        /// <summary>
        /// 鱼的单位价值
        /// </summary>
        [field: SerializeField]
        public float UnitValue { get; init; }

        public override bool Equals(PickableItemDataDTO other)
        {
            if (!base.Equals(other))
                return false;

            if (other is not FishDataDTO fishData)
                return false;

            return FishType == fishData.FishType
                && BaseWeight == fishData.BaseWeight
                && UnitValue == fishData.UnitValue;
        }
    }
}
